home *** CD-ROM | disk | FTP | other *** search
- /**
- GRAB Graph Layout and Browser System
-
- Copyright (c) 1986, 1988 Regents of the University of California
- Copyright (c) 1989, Tera Computer Company
- **/
-
- /* proper.c contains procedures to make a proper matrix for a digraph. */
-
- #include "malloc.h"
- #include "digraph.h"
- #include "debug.h"
- #include "list.h"
-
- OUTEDGE *get_edge();
-
- make_proper(digraph)
- DIGRAPH *digraph;
- /**
- make_proper makes a proper reachability matrix for digraph.
- **/
- {
- if (debug1)
- {
- print_size(digraph, "Size before making proper: \n\t");
- }
-
- make_closure(digraph); /* compute trasitive closure of succedents */
- find_levels(digraph); /* partition into levels */
- undo_closure(digraph); /* restore original edges */
- shorten_spans(digraph); /* add dummies to shorten spans over one level */
-
- if (debug1)
- {
- print_size(digraph, "Size after making proper: \n\t");
- }
- } /* make_proper */
-
- make_closure(digraph)
- DIGRAPH *digraph;
- /**
- make_closure computes the transitive closure of the succeedent set
- of each node in digraph.
- **/
- {
- SET *closed_set; /* closed version of the set */
- NODE *node; /* the current node */
- VNO root_vno; /* vno of current node */
- VNO to_vno; /* each to vertex # */
-
- init_set(closed_set);
-
- each_node(digraph, node)
- loop
- root_vno = Vno(node);
- add_element(closed_set, root_vno); /* node is in its closure */
-
- each_element(Succ_set(node), to_vno)
- loop
- close_set(digraph, closed_set, to_vno, root_vno);
- endloop
-
- copy_set(Succ_set(node), closed_set);
- clear_set(closed_set);
-
- each_element(Succ_set(node), to_vno) /* fix up antecedents */
- loop
- add_element(Ante_set(Node(digraph, to_vno)), root_vno);
- endloop
- endloop
- } /* make_closure */
-
- close_set(digraph, closed_set, vno, root_vno)
- DIGRAPH *digraph;
- SET *closed_set; /* set to add to */
- VNO vno; /* next succedent node */
- VNO root_vno; /* vno of root node */
- /**
- close_set adds the closure of vno's succedents to closed_set. If a
- cycle is detected, the last edge in the cycle is reversed, to
- break the cycle.
- **/
- {
- VNO to_vno; /* each succedent of vno */
-
- if (!in(closed_set, vno))
- {
- add_element(closed_set, vno);
-
- each_element(Succ_set(Node(digraph, vno)), to_vno)
- loop
- if (to_vno == root_vno) /* found cycle */
- {
- int i;
-
- if (debug1)
- {
- printf("close_set: edge %s to %s completes cycle\n",
- Name(Node(digraph, vno)),
- Name(Node(digraph, root_vno)));
- }
-
- for (i = max_edges(Node(digraph, vno), Node(digraph, root_vno));
- i > 0;
- i--)
- {
- if (get_edge(digraph, Node(digraph, vno),
- Node(digraph, root_vno), i) != NULL)
- {
- reverse_edge(digraph, vno, root_vno, i);
- }
- }
- }
- else /* no cycle yet */
- {
- close_set(digraph, closed_set, to_vno, root_vno);
- }
- endloop
- }
- } /* close_set */
-
- find_levels(digraph)
- DIGRAPH *digraph;
- /**
- find_levels partitions the nodes of digraph into levels.
- **/
- {
- LIST *difflist; /* list of set differences */
- ITEM *diff; /* each diff item */
- SET *diff_set; /* each difference */
- SET *level_set; /* each level_set */
- int levno = 0; /* level_set number for debugging */
- NODE *node; /* each node */
-
- init_list(difflist);
- init_set(diff_set); /* initialize the set */
-
- each_node(digraph, node)
- loop
- copy_set(diff_set, Succ_set(node));
- intersect(diff_set, Ante_set(node)); /* compute the intersection */
- xor(diff_set, Succ_set(node)); /* compute the difference */
- add_item(difflist, Vno(node), diff_set);
-
- if (debug)
- {
- printf("\n\nNode = %s: Succedents: ", Name(node));
- print_set(digraph, Succ_set(node));
- printf("\nAntecedents: ");
- print_set(digraph, Ante_set(node));
- printf("\nDifference: ");
- print_set(digraph, diff_set);
- printf("\n");
- }
- endloop
-
- init_set(level_set);
-
- do
- {
- if (debug)
- {
- printf("\n\nDiff list is: ");
-
- each_item(difflist, diff)
- loop
- printf(" %s ", Name(Node(digraph, Key(diff))));
- endloop
-
- printf("\n\n\nLevel %d: ", levno++);
- }
-
- each_item(difflist, diff)
- loop
- if (empty(Set(diff))) /* no differences */
- {
- if (debug)
- {
- printf(" %s ", Name(Node(digraph, Key(diff))));
- }
-
- fflush(stdout);
-
- add_element(level_set, Key(diff));
- remove_item(difflist, diff);
- }
- endloop
-
- each_item(difflist, diff)
- loop
- difference(Set(diff), level_set);
- endloop
-
- add_level(digraph, level_set);
- clear_set(level_set); /* clear the level_set */
- } while (!empty_list(difflist));
-
- {
- LEVEL *level; /* each level */
-
- levno = 0;
-
- each_level(digraph, level) /* assign level numbers */
- loop
- Lno(level) = levno++;
- endloop
- }
-
- if (debug)
- {
- print_levels(digraph);
- }
- } /* find_levels */
-
- undo_closure(digraph)
- DIGRAPH *digraph;
- /**
- undo_closure restores the antecedent and succedent sets of each node in
- digraph to their value before make_closure() was invoked. This is done
- by traversing the edge list of each node.
- **/
- {
- NODE *node; /* each node */
-
- each_node(digraph, node)
- loop
- clear_set(Succ_set(node)); /* clear the succedents */
- clear_set(Ante_set(node)); /* clear the antecedents */
- endloop
-
- fix_ante_succ_sets(digraph);
- } /* undo_closure */
-
- shorten_spans(digraph)
- DIGRAPH *digraph;
- /**
- shorten_spans shortens spans with length greater than one by adding dummy
- nodes to succeeding levels of digraph.
- **/
- {
- LEVEL *level; /* each level */
- MEMBER *member; /* each member */
- SET *long_spans; /* set of nodes to have dummies */
- SET *ante_set; /* antecedents of dummies */
- VNO vno; /* vno of each long span */
-
- init_set(long_spans); /* initialize */
- init_set(ante_set);
-
- each_level(digraph, level)
- loop
- if (Next_level(level) != NULL)
- {
- each_member(level, member)
- loop
- /* compute succedents not in the next level */
- copy_set(long_spans, Succ_set(Member_node(member)));
- difference(long_spans, Members(Next_level(level)));
-
- if (debug)
- {
- printf("shorten_spans: long spans for '%s': ",
- Name(Member_node(member)));
-
- each_element(long_spans, vno)
- loop
- printf(" %s", Name(Node(digraph, vno)));
- endloop
-
- printf("\n");
- }
-
- each_element(long_spans, vno)
- loop
- /* compute antecedents on the current level */
- copy_set(ante_set, Ante_set(Node(digraph, vno)));
- intersect(ante_set, Members(level));
-
- /**
- add a dummy node to the next level --
- fix up antecedents
- **/
- add_dummy(digraph, Next_level(level), vno, ante_set);
-
- if (debug)
- {
- printf("\n\nshorten_spans: shortened %s -> %s span:\n",
- Name(Member_node(member)),
- Name(Node(digraph, vno)));
- print_levels(digraph);
- }
- endloop
- endloop
- }
- endloop
-
- if (debug)
- {
- printf("\nshorten_spans:\n");
- print_levels(digraph);
- }
- } /* shorten_spans */
-
- print_size(digraph, message)
- DIGRAPH *digraph;
- char *message;
- /**
- print_size goes through the digraph and counts the number of nodes and
- edges, and prints out that information along with the message text.
- **/
- {
- NODE *node;
- int n_nodes, n_real, n_dummy, n_coalesced, n_coalescer;
- int n_arc;
-
- n_nodes = n_real = n_dummy = n_coalesced = n_coalescer = 0;
- n_arc = 0;
-
- all_nodes(digraph, node)
- loop
- if (Is_dummy(node))
- {
- n_dummy++;
- n_arc++;
- }
- else if (Coalescer(node))
- {
- n_coalescer++;
- n_arc += card(Succ_set(node));
- }
- else if (Coalesced(node))
- {
- n_coalesced++;
- }
- else
- {
- n_real++;
- n_arc += card(Succ_set(node));
- }
- endloop
-
- n_nodes = n_real + n_dummy;
- printf("%s %d nodes (%d real, %d dummy %d coalescer %d coalesced), %d arcs.\n", message, n_nodes, n_real, n_dummy, n_coalescer, n_coalesced, n_arc);
- } /* print_size */
-